package design_principles.singleton_pattern.code;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 容器单例模式
 */
public class ContainerSingleton {
    /**
     * ------------------------Spring_5核心原理与30个类手写实战 实现--------------------------- 
     * ---------------容器单例模式-------------------------------------- 
     */
    /**
     * 可以指定容量
     */
    private static int CAPACITY = 2;

    /**
     * 构造私有
     */
    private ContainerSingleton() {
    }

    /**
     * 存储单例的容器，可以是各种结构
     */
    private static final Map<String, Object> container = new ConcurrentHashMap<>(CAPACITY);

    /**
     * 获取单例值的一版 来源（书籍 ）
     * 
     * @return
     */
    public static Object getBean(String className) {
        if (!container.containsKey(className)) {
            try {
                Object singleton = Class.forName(className).newInstance();
                container.put(className, singleton);
                return singleton;
            } catch (Exception e) {
                System.out.println(e.getStackTrace());
                return null;
            }

        } else {
            return container.get(className);
        }

    }
    /**
     * 扩展 ：
     * 单例模式为了达到线程安全的目 的，会给方法上锁，以时间换空间。ThreadLocal 将所有的对象全部放 在ThreadLocalMap中，为每个线程都提供一个对象，实际上是以空间换 时间来实现线程隔离的。
     */

    /**
     * --------------------------设计模式之婵 版的实现------------------------------
     * 有上限的多例模式，它是单例模式的一种扩展
     */
    /**
     * 容器
     */
    private static List<ContainerSingleton> list = new Vector<>(CAPACITY);
    /**
     * 静态初始化
     */
    static {
        for (int i = 0; i < CAPACITY; i++) {
            list.add(new ContainerSingleton());
        }
    }

    /**
     * 随机获取实例
     * 
     * @return
     */
    public static ContainerSingleton getSingleton() {
        return list.get(new Random(CAPACITY).nextInt());
    }
}
/**
 * 总结：无论是哪种称呼，都是对单例模式的扩展。依据需要，避免单例模式的问题和缺点，发扬它的优点 存储的容器可以多种多样的结构，满足一下条件即可： 
 * - 保证线程安全 
 * - 容器容量或者有最大值，保证足够的空间 
 * - 容器查找与实际的需求息息相关，甚至可以使用实现的树结构等
 * 
 */
